
#pragma once

#include <iostream>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"

static const int gcap = 5; // for debug

using namespace SemModule;
using namespace MutexModule;

template <typename T>
class RingQueue
{
public:
    RingQueue(int cap = gcap)
        : _cap(cap),
          _rq(cap),
          _blank_sem(cap),
          _p_step(0),
          _data_sem(0),
          _c_step(0)
    {
    }
    void Equeue(const T &in)
    {
        // 生产者
        // 1. 申请信号量，空位置信号量
        _blank_sem.P();
        {
            LockGuard lockguard(_pmutex);
            // 2. 生产
            _rq[_p_step] = in;
            // 3. 更新下标
            ++_p_step;
            // 4. 维持环形特性
            _p_step %= _cap;
        }
        _data_sem.V();
    }
    void Pop(T *out)
    {
        // 消费者
        // 1. 申请信号量，数据信号量
        _data_sem.P();
        {
            LockGuard lockguard(_cmutex);
            // 2. 消费
            *out = _rq[_c_step];
            // 3. 更新下标
            ++_c_step;
            // 4. 维持环形特性
            _c_step %= _cap;
        }
        _blank_sem.V();
    }

private:
    std::vector<T> _rq;
    int _cap;

    // 生产者
    Sem _blank_sem; // 空位置
    int _p_step;
    // 消费者
    Sem _data_sem; // 数据
    int _c_step;

    // 维护多生产，多消费, 2把锁
    Mutex _cmutex;
    Mutex _pmutex;
};

// #pragma once

// #include <iostream>
// #include <vector>

// #include "Sem.hpp"
// #include "Mutex.hpp"
// using namespace SemMoudle;
// using namespace MutexModule;

// static const int defaultcap = 5;

// template <typename T>
// class RingQueue
// {
//     public:
//     RingQueue(int cap = defaultcap)
//     :_cap(cap),
//     _p_step(0),
//     _c_step(0),
//     _blank_sem(cap),
//     _data_sem(0),
//     _rq(cap)
//     {}

//     void Equeue(const T& in)
//     {
//         //生产者

//         //1 申请信号量，空位置信号量

//         //判断 还能不能生产，有没有空位置        
//         _blank_sem.P();
//         {
//             //1 加锁 尾货生产者
//             LockGuard lockguard(_plock);
//             //2 生产数据
//             _rq[_p_step] = in;
//             //3 更新下标 并维护环状特性
//             _p_step = (_p_step + 1) % _cap;
//         }
//         _data_sem.V();
//     }

//     //T Pop()
//     void Pop(T* out) //输出型参数
//     {
//         //消费者
//         //1 申请信号量，数据位置信号量
//         _data_sem.P();
//         {
//             //2 加锁 维护多消费者
//             LockGuard lockguard(_clock);
//             //3 消费数据
//             *out = _rq[_c_step];
//             //4 更新下标 维护环状结构
//             _c_step = (_c_step + 1) % _cap;
//         }
//         _blank_sem.V();
//     }

//     ~RingQueue()
//     {}
//     private:
//     std::vector<T> _rq;
//     int _cap;

//     //生产者
//     Sem _blank_sem;  //空位置 维护 环状类型
//     int _p_step;

//     //消费者
//     Sem _data_sem; //数据位置 维护环状类型
//     int _c_step;

//     //只是单单线程 就不需要加锁
//     // 单单: cc, pp -> 互斥关系不需要维护，互斥与同步
//     // 多多：cc, pp -> 之间的互斥关系！
//     // 维护多生产，多消费, 2把锁
//     Mutex _plock;
//     Mutex _clock;

// };